<template>
  <div class="t-gen-form">
    <Suspense>
      <template #default>
        <el-form
          ref="genFormRef"
          :disabled="formConf?.disabled"
          :label-position="formConfCopy.labelPosition"
          :label-width="formConfCopy.labelWidth + 'px'"
          :model="formModel"
          :rules="formRules"
          :size="formConfCopy.size"
          :validate-on-rule-change="false"
          @validate="handleFormValidate"
          @submit.native.prevent
        >
          <el-row
            :gutter="formConfCopy.gutter"
            style="margin: 0"
          >
            <generate-form-item
              v-for="(item, index) in getFields"
              :key="`${item.key}`"
              :cid="item.vModel"
              :index="index"
              :item="item"
              v-model:models="formModel"
              :seq-no="item.seqNo"
              v-show="isFieldShow(item) && isNotHideField(item)"
              @next="nextPage"
              @prev="prevPage"
              @input-change="onInputChange"
              @ocr-success="handleOcrSuccess"
            />

            <el-col v-if="formConfCopy.formBtns">
              <el-form-item
                class="submit-btn-form-item"
                size="large"
                style="margin-top: 30px"
              >
                <el-button
                  class="submit-btn"
                  type="primary"
                  :loading="btnLoading"
                  @click="submitForm"
                  :color="formThemeConfig?.themeColor"
                >
                  {{ formThemeConfig?.submitBtnText || "提交" }}
                </el-button>
                <el-button
                  v-if="formConfCopy.resetBtn"
                  @click="resetForm"
                >
                  重置
                </el-button>
              </el-form-item>
            </el-col>
          </el-row>
        </el-form>
      </template>
      <template #fallback>
        <async-loading />
      </template>
    </Suspense>
  </div>
</template>

<script setup lang="ts" name="GenerateForm">
import { computed, inject, nextTick, onBeforeMount, Ref, ref, watch } from "vue";
import GenerateFormItem from "./GenerateFormItem.vue";
import { cloneDeep, throttle } from "lodash-es";
import { saveFormData } from "../../utils/db";
import { useRoute, useRouter } from "vue-router";
import { useFormValidateRule } from "./hooks/useFormValidateRule";
import { useUserForm } from "@/stores/userForm";
import { storeToRefs } from "pinia";
import { useFormLogic } from "./hooks/useFormLogicHook";
import type { FormInstance } from "element-plus";
import { FormItemProp } from "element-plus";
import { useExamForm } from "@/views/formgen/components/GenerateForm/hooks/useExamHook";
import { useFormSeqNo } from "@/views/formgen/components/GenerateForm/hooks/useSeqNoHook";
import AsyncLoading from "@/components/TLoading/asyncLoading.vue";
import { useFormOption } from "@/views/formgen/components/FormItem/hooks/useFormOptionHook";

const props = defineProps({
  // 表单配置
  formConf: {
    type: Object,
    required: true
  },
  // 表单数据对象
  pageFormModel: {
    type: Object,
    required: false
  },
  // 是否是子表单
  isSubForm: {
    type: Boolean,
    required: false,
    default: false
  },
  // 是否显示隐藏字段
  showHiddenField: {
    type: Boolean,
    required: false,
    default: false
  }
});

const genFormRef = ref<FormInstance>();

const formConfCopy = ref<any>(cloneDeep(props.formConf));
const formModel = ref<any>(cloneDeep(props.pageFormModel));
const formRules = ref({});

const btnLoading = ref(false);

// 监听器：formModel
watch(
  formModel,
  val => {
    emit("update:pageFormModel", val);
  },
  { deep: true }
);

// 计算属性：hideFields
const userFormStore = useUserForm();
const { hiddenFormItemIds, customIdMap } = storeToRefs(userFormStore);
const hideFields = computed(() => hiddenFormItemIds.value || []);

const formThemeConfig = inject(
  "formThemeConfig",
  ref({
    showFormNumber: false,
    submitBtnText: "提交",
    themeColor: ""
  })
);

// 监听显示序号开关的变化 把序号重置为0 不然会累加 主题页面开关会错误
watch(
  () => formThemeConfig.value.showFormNumber,
  () => {
    initFormSeqNo(formConfCopy.value.fields);
  },
  { deep: true }
);

const getFields = computed(() => {
  return formConfCopy.value.fields;
});

// 是否是隐藏字段 或者开启了显示隐藏字段
const isNotHideField = (item: any) => {
  return !item.hideType || props.showHiddenField;
};

const { lastSeqNo } = useFormSeqNo();

// 创建阶段
onBeforeMount(() => {
  // 初始化动态数据 比如SELECT等远程数据
  initDynamicOptions(formConfCopy.value.fields);
  // 初始化默认值
  initFormData(formConfCopy.value.fields, formModel.value);
  // 初始化序号
  initFormSeqNo(formConfCopy.value.fields);
  // 构建表单校验规则
  buildRules(formConfCopy.value.fields, formRules);
  // url携带值保存
  getRouteVals();
  // 加载考试设置
  examHook.handleExamSetting();
});

/**
 * 存储路由的val
 */
const getRouteVals = () => {
  Object.keys(route.query).forEach(key => {
    if (!formModel.value[key]) {
      formModel.value[key] = route.query[key];
    }
  });
};

const examHook = useExamForm(() => {
  emit("submit", { formModel: formModel.value });
});

/**
 * 构建表单校验规则
 * @param componentList
 * @param rules
 */
const buildRules = (componentList: any[], rules: Ref<any>) => {
  componentList.forEach(cur => {
    // 逻辑城市显示并且不是隐藏字段
    if (isFieldShow(cur) && !cur.hideType) {
      buildRule(cur, rules, formModel);
    }
  });
};

const handleFormValidate = (prop: FormItemProp, isValid: boolean, message: string) => {
  console.log(prop);
  console.log(isValid);
  console.log(message);
};

let router = useRouter();
let route = useRoute();

const getRouteValue = (key: string): any => {
  let val = route.query[key] || route.query[customIdMap.value[key]];
  if (route && route.query && undefined !== val) {
    return val;
  }
  return null;
};

const formOption = useFormOption();
/**
 * 初始化动态选项 比如多选的接口取值 等
 * @param componentList
 */
const initDynamicOptions = async (componentList: any[]) => {
  for (const cur of componentList) {
    const config = cur.config;
    cur.config.options = await formOption.getOptions(config);
  }
};
// 初始化表单默认值
const initFormData = (componentList: any[], formData: any) => {
  componentList.forEach(cur => {
    const config = cur.config;
    // 如果存在分页带回的数据
    if (cur.vModel && !formData[cur.vModel]) {
      const defaultValue = getRouteValue(cur.vModel) || config.defaultValue;
      formData[cur.vModel] = defaultValue;
      // 处理默认值的逻辑 不包括“”
      if (defaultValue !== undefined && defaultValue !== null) {
        handleLogicChange(config.defaultValue, cur.vModel, {});
      }
      console.log(formData[cur.vModel]);
    }
    if (config.children) {
      initFormData(config.children, formData);
    }
  });
  if (!props.isSubForm) {
    handleHiddenFieldDefaultValue(formData);
  }
};

// 隐藏字段默认值处理 如果符合自定义字段的规则的话 就填充到表单值中
const handleHiddenFieldDefaultValue = (formData: any) => {
  const queryParams = router.currentRoute.value.query;
  if (queryParams) {
    for (let key in queryParams) {
      if (/\d/.test(key) && !formData[key]) {
        formData[key] = queryParams[key];
      }
    }
  }
};

const { buildRule } = useFormValidateRule();

const { logicShowHandle } = useFormLogic(formConfCopy, formModel, formRules, buildRule);

const handleLogicChange = (value: any, field: any, item: any) => {
  logicShowHandle(value, field, item);
  nextTick(() => {
    initFormSeqNo(formConfCopy.value.fields);
  });
};

/**
 * 重置表单
 */
const resetForm = () => {
  formConfCopy.value = cloneDeep(props.formConf);
  genFormRef.value?.resetFields();
};

/**
 * 验证表单
 */
const validateForm = () => {
  return new Promise(resolve => {
    genFormRef.value?.validate((valid: boolean) => {
      resolve(valid);
    });
  });
};

const scrollToItem = () => {
  setTimeout(() => {
    const isError = document.getElementsByClassName("is-error");
    const input = isError[0].querySelector("input");
    if (input) {
      input.focus();
    } else {
      document.getElementsByClassName("is-error")[0].scrollIntoView();
    }
  }, 100);
};

/**
 * 提交表单
 */
const submitForm = throttle(function () {
  genFormRef.value?.validate((valid: boolean) => {
    console.log(formModel.value);
    if (!valid) {
      scrollToItem();
      return false;
    }
    // 考试是否达到提交要求
    if (!examHook.handleExamCanSubmit()) {
      return;
    }
    if (valid) {
      btnLoading.value = true;
      setTimeout(() => {
        btnLoading.value = false;
      }, 1000);
      console.log(JSON.stringify(formModel.value));
      emit("submit", { formModel: formModel.value });
      return true;
    }
  });
}, 8000);

/**
 *
 * @param value 值
 * @param field 字段id
 * @param item 定义
 */
const onInputChange = (value: any, field: any, item: any) => {
  emit("on-change", field, value, formModel);
  if (value !== undefined && value != null) {
    genFormRef.value?.clearValidate(field);
  } else {
    genFormRef.value?.validateField(field);
  }
  handleLogicChange(value, field, item);
  tempSaveFormData();
};

const nextPage = (page: number) => {
  switchPage("next", page);
};

const prevPage = (page: number) => {
  emit("prev", {
    page,
    startSeqNo: formConfCopy.value.startSeqNo,
    endSeqNo: lastSeqNo.value,
    formModel: formModel.value
  });
};

const switchPage = (eventName: string, page: number) => {
  genFormRef.value?.validate((valid: boolean) => {
    if (!valid) {
      scrollToItem();
      return false;
    }
    //@ts-ignore
    emit(eventName, {
      page,
      startSeqNo: formConfCopy.value.startSeqNo,
      endSeqNo: lastSeqNo.value,
      formModel: formModel.value
    });
    return true;
  });
};

/**
 * 字段是否显示 受逻辑控制显示隐藏
 * @param item
 */
const isFieldShow = (item: any) => {
  return !hideFields.value || !hideFields.value.length || hideFields.value.indexOf(item.vModel) === -1;
};

/**
 * 初始化序号
 * @param index
 * @param item
 */
const initFormSeqNo = (fields: any[]) => {
  if (!formThemeConfig.value || formThemeConfig.value.showFormNumber !== true) {
    // 如果是lastSeqNo.value != 0 说明是关掉了序号
    fields.forEach(item => {
      item.seqNo = undefined;
      lastSeqNo.value = 0;
    });
    return null;
  }
  let seqNo = formConfCopy.value.startSeqNo || 0;
  fields.forEach(item => {
    if (isFieldShow(item) && !item.config.displayType) {
      seqNo = seqNo + 1;
      item.seqNo = seqNo;
      lastSeqNo.value = seqNo;
    }
  });
};

/**
 * OCR 识别成功
 * @param val
 */
const handleOcrSuccess = (val: any) => {
  Object.keys(val).forEach(key => {
    formModel.value[key] = val[key];
    const index = formConfCopy.value.fields.findIndex((item: any) => item.vModel === key);
    if (index === -1) return;
    const item = formConfCopy.value.fields[index];
    item.key = new Date() + key;
  });
};

/**
 * 临时保存
 */
const tempSaveFormData = throttle(function () {
  if (props.formConf?.setting && props.formConf?.setting?.saveNotSubmitStatus) {
    saveFormData(formModel.value, props.formConf.formKey);
  }
}, 430);

/**]
 * 滚动到某个字段
 */
const scrollToField = (fieldId: string) => {
  genFormRef.value?.scrollToField(fieldId);
};

defineExpose({
  validateForm,
  resetForm,
  formModel,
  scrollToField,
  genFormRef
});

const emit = defineEmits(["submit", "on-change", "next", "prev", "update:pageFormModel"]);
</script>
<style lang="scss" scoped>
@media screen and (max-width: 1067px) {
  .t-gen-form {
    width: 100%;
    padding: 12px 10px !important;

    .el-form {
      width: 100%;
    }
  }
}

.submit-btn-form-item {
  :deep(.el-form-item__content) {
    display: flex;
    align-items: center !important;
    justify-content: center !important;
  }
}

.submit-btn:hover {
  border: none;
  transform: scale(1.02);
  transition: all 0.3s ease;
}

.t-gen-form {
  width: 100%;
  padding: 12px 28px;

  .el-form {
    width: 100%;
  }
}

.list-move, /* 对移动中的元素应用的过渡 */
.list-enter-active,
.list-leave-active {
  transition: all 0.5s ease;
}

.list-enter-from,
.list-leave-to {
  opacity: 0;
  transform: translateX(30px);
}

/* 确保将离开的元素从布局流中删除
  以便能够正确地计算移动的动画。 */
.list-leave-active {
  position: absolute;
}
</style>
